package bet

import (
	"context"
	"encoding/json"
	"game_server/framework/global"
	"game_server/framework/message"
	"game_server/framework/task"
	"game_server/game"
	"game_server/game/model"
	"game_server/proto"
	"game_server/tool"
	"github.com/duke-git/lancet/v2/convertor"
	"github.com/spf13/viper"
	"strings"
	"time"
)

type BetReq struct {
	BetCoins  int64 `json:"betCoins"`
	Area      int   `json:"area"`
	RoomLevel int   `json:"roomLevel"`
}

func BetHandler(taskWrapper *task.TaskWrapper) *task.TaskWrapper {
	defer func() {
		err := recover()
		if err != nil {
			global.Logger.Errorf("err:%v", err)
		}
	}()
	defer global.Logger.Info("package:[bet]:::function:[BetHandler]<======")
	global.Logger.Infof("======>package:[bet]:::function:[BetHandler]:::id:%v", taskWrapper.ReceiverId)
	betReq := &BetReq{}
	json.Unmarshal([]byte(convertor.ToString(taskWrapper.MessageWrapper.Data)), betReq)
	roomInfo := game.GameManagerInstance().RoomInfos[betReq.RoomLevel]
	if roomInfo.Status != model.WAITING_BET {
		messageWrapper := &message.MessageWrapper{Code: proto.BET, Data: nil, ResultCode: message.FAIL, MsgCode: 0}
		task := &task.TaskWrapper{
			ReceiverId:     taskWrapper.ReceiverId,
			MessageWrapper: messageWrapper,
			SenderIds:      []int64{taskWrapper.ReceiverId},
		}
		return task
	}
	if roomInfo.Countdown <= 1 {
		messageWrapper := &message.MessageWrapper{Code: proto.BET, Data: nil, ResultCode: message.FAIL, MsgCode: 0}
		task := &task.TaskWrapper{
			ReceiverId:     taskWrapper.ReceiverId,
			MessageWrapper: messageWrapper,
			SenderIds:      []int64{taskWrapper.ReceiverId},
		}
		return task
	}
	arr := strings.Split(roomInfo.RoomConfig.Chips, ",")
	minBetCoins, _ := convertor.ToInt(arr[0])
	if betReq.BetCoins < minBetCoins {
		messageWrapper := &message.MessageWrapper{Code: proto.BET, Data: nil, ResultCode: message.FAIL, MsgCode: 1}
		task := &task.TaskWrapper{
			ReceiverId:     taskWrapper.ReceiverId,
			MessageWrapper: messageWrapper,
			SenderIds:      []int64{taskWrapper.ReceiverId},
		}
		return task
	}
	playerInfo, ok := roomInfo.PlayerInfos.Get(taskWrapper.ReceiverId)
	if !ok {
		messageWrapper := &message.MessageWrapper{Code: proto.BET, Data: nil, ResultCode: message.FAIL, MsgCode: 2}
		task := &task.TaskWrapper{
			ReceiverId:     taskWrapper.ReceiverId,
			MessageWrapper: messageWrapper,
			SenderIds:      []int64{taskWrapper.ReceiverId},
		}
		return task
	}
	if playerInfo.BetState == 1 {
		messageWrapper := &message.MessageWrapper{Code: proto.BET, Data: nil, ResultCode: message.FAIL, MsgCode: 5}
		task := &task.TaskWrapper{
			ReceiverId:     taskWrapper.ReceiverId,
			MessageWrapper: messageWrapper,
			SenderIds:      []int64{taskWrapper.ReceiverId},
		}
		return task
	}
	if betReq.BetCoins > playerInfo.Coins {
		messageWrapper := &message.MessageWrapper{Code: proto.BET, Data: nil, ResultCode: message.FAIL, MsgCode: 3}
		task := &task.TaskWrapper{
			ReceiverId:     taskWrapper.ReceiverId,
			MessageWrapper: messageWrapper,
			SenderIds:      []int64{taskWrapper.ReceiverId},
		}
		return task
	}
	betInfo, ok := roomInfo.BetInfos.Get(playerInfo.Id)
	if ok {
		if betInfo.BetCoins+betReq.BetCoins > roomInfo.RoomConfig.BetMax {
			messageWrapper := &message.MessageWrapper{Code: proto.BET, Data: nil, ResultCode: message.FAIL, MsgCode: 4}
			task := &task.TaskWrapper{
				ReceiverId:     taskWrapper.ReceiverId,
				MessageWrapper: messageWrapper,
				SenderIds:      []int64{taskWrapper.ReceiverId},
			}
			return task
		}
		betInfo.BetCoins += betReq.BetCoins
	} else {
		if betReq.BetCoins > roomInfo.RoomConfig.BetMax {
			betReq.BetCoins = roomInfo.RoomConfig.BetMax
		}
		betInfo = &model.BetInfo{
			RoomId:          roomInfo.RoomConfig.Id,
			RoomLevel:       betReq.RoomLevel,
			RoomPeriods:     roomInfo.RoomConfig.Periods,
			RoomArea:        betReq.Area,
			PlayerId:        taskWrapper.ReceiverId,
			NickName:        playerInfo.NickName,
			BetCoins:        betReq.BetCoins,
			IsRobot:         false,
			WinCoins:        int64(0),
			ProfitLossCoins: int64(0),
			GameResult:      model.NO,
		}
		roomInfo.BetInfos.Set(playerInfo.Id, betInfo)
	}
	playerInfo.Coins = playerInfo.Coins - betReq.BetCoins
	playerInfo.LastBetTimeStamp = tool.CurrentTimestamp()
	playerInfo.IsGaming = true
	playerInfoRes := proto.PlayerInfoRes{IsSelf: true}
	convertor.CopyProperties(&playerInfoRes, playerInfo)
	json, _ := convertor.ToJson(playerInfo)
	tokenTime := viper.GetInt("redis.token-time")
	global.RedisClient.Set(context.Background(), viper.GetString("redis.player-key")+convertor.ToString(playerInfo.Id), json, time.Duration(tokenTime)*time.Minute)

	messageWrapper := &message.MessageWrapper{Code: proto.BET, Data: playerInfoRes, ResultCode: message.SUCCESS, MsgCode: -1}
	task := &task.TaskWrapper{
		ReceiverId:     taskWrapper.ReceiverId,
		MessageWrapper: messageWrapper,
		SenderIds:      []int64{taskWrapper.ReceiverId},
	}
	return task
}
